#include "gateway/beast_http/http_server.hpp"
#include "gateway/beast_http/router.hpp"
#include "logger/LoggerManager.h"
#include "config/config.h"
#include "database/redis_pool.h"
#include "framework/service_bus_v2.h"
#include <iostream>
#include <fstream>
#include "nlohmann/json.hpp"

using cpp_backend::config::Config;

int main(int argc, char* argv[]) {
    try {
        // 1) 加载配置
        auto& cfg = Config::Instance();
        if (!cfg.LoadFromFile("config/server.json")) {
            std::cerr << "Failed to load config/server.json" << std::endl;
            return 1;
        }
        const auto& s = cfg.GetServerConfig();

        // 2) 初始化Redis与ServiceBusV2
        auto& redis_pool = cpp_backend::database::RedisPool::Instance();
        if (!redis_pool.Initialize()) {
            std::cerr << "Failed to init Redis pool" << std::endl;
            return 1;
        }
        auto& bus = cpp_backend::framework::ServiceBusV2::Instance();
        bus.Initialize(&redis_pool);

        // 3) 构建路由：优先从 config/server.json 的 gateway.routes 读取
        auto router = std::make_shared<gateway::beast_http::Router>();
        gateway::beast_http::GatewaySettings gw_settings;
        try {
            std::ifstream ifs("config/server.json");
            if (ifs.is_open()) {
                nlohmann::json j; ifs >> j; ifs.close();
                if (j.contains("gateway") && j["gateway"].contains("routes")) {
                    router->load_from_json(j["gateway"]["routes"]);
                }
                if (j.contains("gateway") && j["gateway"].contains("access_log")) {
                    gw_settings.access_log_enable = j["gateway"]["access_log"].get<bool>();
                }
                if (j.contains("gateway") && j["gateway"].contains("jwt")) {
                    auto& jj = j["gateway"]["jwt"];
                    gw_settings.jwt.enable = jj.value("enable", false);
                    gw_settings.jwt.require_signature = jj.value("require_signature", false);
                    if (jj.contains("secret")) gw_settings.jwt.secret = jj["secret"].get<std::string>();
                    if (jj.contains("alg")) gw_settings.jwt.alg = jj["alg"].get<std::string>();
                    if (jj.contains("public_key_path")) gw_settings.jwt.public_key_path = jj["public_key_path"].get<std::string>();
                    if (jj.contains("iss")) gw_settings.jwt.issuer = jj["iss"].get<std::string>();
                    if (jj.contains("aud")) {
                        if (jj["aud"].is_string()) gw_settings.jwt.audience.push_back(jj["aud"].get<std::string>());
                        else if (jj["aud"].is_array()) for (const auto& a : jj["aud"]) gw_settings.jwt.audience.push_back(a.get<std::string>());
                    }
                    if (jj.contains("keys") && jj["keys"].is_array()) {
                        for (const auto& item : jj["keys"]) {
                            if (item.contains("kid") && item.contains("path") &&
                                item["kid"].is_string() && item["path"].is_string()) {
                                gw_settings.jwt.key_paths[item["kid"].get<std::string>()] = item["path"].get<std::string>();
                            }
                        }
                    }
                }
                if (j.contains("gateway") && j["gateway"].contains("rate_limit")) {
                    auto& rl = j["gateway"]["rate_limit"];
                    gw_settings.rl.enable = rl.value("enable", false);
                    gw_settings.rl.rps = rl.value("rps", 1000);
                    if (rl.contains("mode")) gw_settings.rl.mode = rl["mode"].get<std::string>();
                    gw_settings.rl.burst = rl.value("burst", 0);
                    if (rl.contains("whitelist_ips")) for (const auto& v : rl["whitelist_ips"]) gw_settings.rl.whitelist_ips.push_back(v.get<std::string>());
                    if (rl.contains("blacklist_ips")) for (const auto& v : rl["blacklist_ips"]) gw_settings.rl.blacklist_ips.push_back(v.get<std::string>());
                    if (rl.contains("whitelist_paths")) for (const auto& v : rl["whitelist_paths"]) gw_settings.rl.whitelist_paths.push_back(v.get<std::string>());
                    if (rl.contains("blacklist_paths")) for (const auto& v : rl["blacklist_paths"]) gw_settings.rl.blacklist_paths.push_back(v.get<std::string>());
                    gw_settings.rl.redis_enable = rl.value("redis_enable", false);
                    if (rl.contains("redis_prefix")) gw_settings.rl.redis_prefix = rl["redis_prefix"].get<std::string>();
                }
                if (j.contains("gateway") && j["gateway"].contains("authz")) {
                    auto& az = j["gateway"]["authz"];
                    if (az.contains("rules") && az["rules"].is_array()) {
                        for (const auto& r : az["rules"]) {
                            if (r.contains("prefix") && r.contains("roles") && r["roles"].is_array()) {
                                gateway::beast_http::GatewaySettings::Authz::Rule rule;
                                rule.prefix = r["prefix"].get<std::string>();
                                for (const auto& role : r["roles"]) rule.roles.push_back(role.get<std::string>());
                                gw_settings.authz.rules.push_back(std::move(rule));
                            }
                        }
                    }
                }
            }
        } catch (...) {}
        // 默认路由（兜底）
        router->add("/api/ping", "ping_service");

        // 4) 启动HTTP服务器（初始化日志）
        auto lg = cfg.GetLogConfig();
        logger::LogConfig lc = lg;
        lc.moduleName = "Gateway"; // 覆盖模块名
        logger::LoggerManager::getInstance().init(lc);
        gateway::beast_http::HttpServer server(
            s.host,
            static_cast<unsigned short>(s.http_port),
            s.io_thread_count <= 0 ? 0 : s.io_thread_count,
            s.thread_pool_size <= 0 ? 0 : s.thread_pool_size);
        server.set_router(router);
        server.set_settings(gw_settings);

        // 路由热更新线程：每5秒检查配置文件变更
        std::thread reloader([router]() {
            namespace fs = std::filesystem;
            const std::string path = "config/server.json";
            std::error_code ec;
            auto last = fs::last_write_time(path, ec);
            for (;;) {
                std::this_thread::sleep_for(std::chrono::seconds(5));
                auto cur = fs::last_write_time(path, ec);
                if (!ec && cur != last) {
                    try {
                        std::ifstream ifs(path);
                        if (ifs.is_open()) {
                            nlohmann::json j; ifs >> j; ifs.close();
                            if (j.contains("gateway") && j["gateway"].contains("routes")) {
                                router->load_from_json(j["gateway"]["routes"]);
                                last = cur;
                            }
                        }
                    } catch (...) {}
                }
            }
        });
        reloader.detach();

        server.run();
        return 0;
    } catch (const std::exception& e) {
        std::cerr << "Fatal: " << e.what() << std::endl;
        return 1;
    }
}
